
Imports System.IO
Imports System.Threading
Imports std
Imports storoomc

'for any operation, should check whether key or buff is valid in public function,
'and any protected/private function can trust the key/buff are always available.
'then can save a call if the data input is not valid.
Partial Public Class storoomDistrTM
    Inherits distributeOperation2
    Implements storoomThreadModel

    Public distributeOperationHoldtime As Int64 = defaultHoldTime
    Private caller As storoomOper(Of storoomDistrTM) = Nothing
    Private cbs As vector(Of _do(Of jobType, storageInterface, Object, Boolean)) = Nothing

    Public Sub New(ByVal caller As storoomOper(Of storoomDistrTM))
        MyBase.New()
        assert(Not caller Is Nothing)
        Me.caller = caller
    End Sub

    Private Function singleDistrInfoBooleanDistrOperation(ByVal d As _do(Of Boolean), _
                                                          Optional ByVal holdtime As Int64 = npos) As Boolean
        assert(Not d Is Nothing)
        If holdtime = npos Then
            holdtime = distributeOperationHoldtime
        End If
        Dim rtn As Boolean
        Return MyBase.distrOperation(Of singleDistrInfo(Of Boolean), Boolean, Boolean) _
                                    (True, rtn, Function()
                                                    Return singleDistrInfo(Of Boolean).createInfo( _
                                                        Function() As ternary
                                                            Return ifoper(d(), ternary.true, ternary.false)
                                                        End Function, _
                                                        Function(ByRef rst As ternary) As Boolean
                                                            Return rst = ternary.true
                                                        End Function)
                                                End Function, 1, holdtime) AndAlso _
               rtn
    End Function

    Private Shadows Function distrOperation(Of infoType As distrInfo(Of argType, returnType), _
                                               argType, returnType) _
                                           (ByVal arg As argType, ByRef rtn As returnType, _
                                            ByVal createInfo As distrInfo(Of argType,  _
                                                                             returnType).createInfoDelegate, _
                                            ByVal slices As vector(Of storageInterface), _
                                            Optional ByVal holdtime As Int64 = npos) As Boolean
        If slices Is Nothing OrElse slices.size() = 0 Then
            Return False
        End If

        If holdtime = npos Then
            holdtime = distributeOperationHoldtime
        End If
        Dim arg2 As pair(Of argType, vector(Of storageInterface)) = Nothing
        arg2 = make_pair(arg, slices)
        Return MyBase.distrOperation(Of infoType, pair(Of argType, vector(Of storageInterface)), returnType) _
                                    (arg2, rtn, createInfo, slices.size(), holdtime)
    End Function

    Private Sub runcallback(ByVal jobType As jobType, ByVal slice As storageInterface, ByRef obj As Object)
        If Not callback(cbs, jobType, slice, obj) Then
            raiseError(errorHandle.errorType.exclamation,
                       "cannot run callback ", jobType_String(jobType), " on slice ", caller.showslice(slice))
        End If
    End Sub

    Public Function ishealthSlice(ByVal slice As storageInterface) As Boolean
        Return caller.ishealthSlice(slice)
    End Function

    Public Function write(ByVal key As String,
                          ByVal buff As bytes,
                          ByVal slice As storageInterface) As Boolean Implements storoomThreadModel.write
        Return singleDistrInfoBooleanDistrOperation(Function() As Boolean
                                                        Return slice.write(key, buff)
                                                    End Function)
    End Function

    Public Function retire(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.retire
        Dim arg As Boolean = False
        Dim rtn As Boolean = True
        If Not distrOperation(Of retireInfo, Boolean, Boolean) _
                             (arg, rtn, AddressOf retireInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when retire", errorHandle.errorType.exclamation)
            Return False
        Else
            Return rtn
        End If
    End Function

    Public Function empty(ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.empty
        Dim rtn As Boolean = True
        Dim arg As Boolean = False
        If Not distrOperation(Of emptyInfo, Boolean, Boolean) _
                             (arg, rtn, AddressOf emptyInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when check empty", errorHandle.errorType.exclamation)
            Return ternary.unknown
        Else
            Return ifoper(rtn, ternary.true, ternary.false)
        End If
    End Function

    Public Function close(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.close
        Dim rtn As Boolean = False
        Dim arg As Boolean = False
        If Not distrOperation(Of closeInfo, Boolean, Boolean) _
                             (arg, rtn, AddressOf closeInfo.createInfo, slices, maxInt64) Then
            raiseError("cannot finish distrOperation when close", errorHandle.errorType.exclamation)
            rtn = False
        Else
            rtn = True
        End If

        [stop]()
        Return rtn
    End Function

    Public Function open(ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.open
        Dim arg As Boolean = False
        Dim rtn As Boolean = True
        If Not distrOperation(Of openInfo(Of Boolean), Boolean, Boolean) _
                             (arg, rtn, AddressOf openInfo(Of Boolean).createInfo, slices) Then
            raiseError("cannot finish distrOperation when open", errorHandle.errorType.exclamation)
            Return False
        Else
            Return rtn
        End If
    End Function

    Public Function seek(ByVal key As String,
                         ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.seek
        Dim rtn As Boolean
        If Not distrOperation(Of seekInfo, String, Boolean) _
                             (key, rtn, AddressOf seekInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when seek", errorHandle.errorType.exclamation)
            Return ternary.unknown
        Else
            Return ifoper(rtn, ternary.true, ternary.false)
        End If
    End Function

    Public Function read(ByVal key As String, ByRef buff As bytes, _
                         ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.read
        Dim rtn As Boolean = False
        If Not distrOperation(Of readInfo, String, bytes) _
                             (key, buff, AddressOf readInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when read", errorHandle.errorType.exclamation)
            rtn = False
        ElseIf buff Is Nothing Then
            rtn = False
        Else
            rtn = True
        End If

        Return rtn
    End Function

    Public Function list(ByVal l As vector(Of String), _
                         ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.list
        Dim arg As Boolean = False
        If Not distrOperation(Of listInfo, Boolean, vector(Of String)) _
                             (arg, l, AddressOf listInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when list", errorHandle.errorType.exclamation)
            Return False
        Else
            Return True
        End If
    End Function

    Public Function delete(ByVal key As String, _
                           ByVal slices As vector(Of storageInterface), _
                           ByVal createInfo As deleteInfo.createInfoDelegate) As Boolean
        Dim deleted As Boolean = False
        If Not distrOperation(Of deleteInfo, String, Boolean)(key, deleted, createInfo, slices) Then
            raiseError("cannot finish distrOperation when delete", errorHandle.errorType.exclamation)
            Return False
        Else
            Return deleted
        End If
    End Function

    Public Function delete(ByVal key As String, _
                           ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.delete
        Return delete(key, slices, AddressOf deleteInfo.createInfo)
    End Function

    Public Function full(ByVal slices As vector(Of storageInterface), _
                         ByVal createInfo As fullInfo.createInfoDelegate, _
                         ByVal initialValue As Boolean) As ternary
        Dim rtn As Boolean = initialValue
        If Not distrOperation(Of fullInfo, Boolean, Boolean)(False, rtn, createInfo, slices) Then
            raiseError("cannot finish distrOperation when check full", errorHandle.errorType.exclamation)
            Return ternary.unknown
        Else
            Return ifoper(rtn, ternary.true, ternary.false)
        End If
    End Function

    Public Function full(ByVal slices As vector(Of storageInterface)) As ternary Implements storoomThreadModel.full
        Return full(slices, AddressOf fullInfo.createInfo, True)
    End Function

    Public Function shareTypeFullImpl(ByVal slices As vector(Of storageInterface)) As ternary _
                                     Implements storoomThreadModel.shareTypeFull
        Return full(slices, AddressOf shareTypeFullInfo.createInfo, False)
    End Function

    Public Function capacity(ByRef cap As UInt64, _
                             ByVal slices As vector(Of storageInterface), _
                             ByVal createInfo As capInfo.createInfoDelegate, _
                             ByVal initialValue As UInt64) As Boolean
        cap = initialValue
        If distrOperation(Of capInfo, Boolean, UInt64)(False, cap, createInfo, slices) Then
            Return True
        Else
            raiseError("cannot finish distrOperation when check capacity", errorHandle.errorType.exclamation)
            Return False
        End If
    End Function

    Public Function capacity(ByRef cap As UInt64, _
                             ByVal slices As vector(Of storageInterface)) As Boolean _
                            Implements storoomThreadModel.capacity
        Return capacity(cap, slices, AddressOf capInfo.createInfo, 0)
    End Function

    Public Function shareTypeCapacityImpl(ByRef cap As UInt64, _
                                          ByVal slices As vector(Of storageInterface)) As Boolean _
                                         Implements storoomThreadModel.shareTypeCapacity
        Return capacity(cap, slices, AddressOf shareTypeCapInfo.createInfo, maxUInt64)
    End Function

    Public Function valuesize(ByRef sz As UInt64, _
                              ByVal slices As vector(Of storageInterface)) As Boolean _
                             Implements storoomThreadModel.valuesize
        If Not distrOperation(Of sizeInfo, Boolean, UInt64) _
                             (False, sz, AddressOf sizeInfo.createInfo, slices) Then
            raiseError("cannot finish distrOperation when check valuesize", errorHandle.errorType.exclamation)
            Return False
        Else
            Return True
        End If
    End Function

    Public Function sizeof(ByVal key As String, ByRef size As UInt64, _
                           ByVal slices As vector(Of storageInterface), _
                           ByVal createInfo As sizeofInfo.createInfoDelegate)
        Dim rtn As pair(Of UInt64, Boolean) = Nothing
        rtn = make_pair(size, False)
        If Not distrOperation(Of sizeofInfo, String, pair(Of UInt64, Boolean))(key, rtn, createInfo, slices) Then
            raiseError("cannot finish distrOperation when get key value size", errorHandle.errorType.exclamation)
            Return False
        ElseIf Not rtn.second Then
            Return False
        Else
            size = rtn.first
            Return True
        End If
    End Function

    Public Function sizeof(ByVal key As String, ByRef size As UInt64, _
                           ByVal slices As vector(Of storageInterface)) As Boolean Implements storoomThreadModel.sizeof
        Return sizeof(key, size, slices, AddressOf sizeofInfo.createInfo)
    End Function

    Public Function keycount(ByRef count As UInt64, _
                             ByVal slices As vector(Of storageInterface)) As Boolean _
                            Implements storoomThreadModel.keycount
        If distrOperation(Of keycountInfo, Boolean, UInt64) _
                         (True, count, AddressOf keycountInfo.createInfo, slices) Then
            Return True
        Else
            raiseError("cannot finish distrOperation when get keycount", errorHandle.errorType.exclamation)
            Return False
        End If
    End Function

    Public Function singleThreadWork(ByVal d As _do(Of Boolean)) As Boolean _
                                    Implements storoomThreadModel.singleThreadWork
        Return singleDistrInfoBooleanDistrOperation(d)
    End Function

    Public Function registerCallback(ByVal d As _do(Of jobType, storageInterface, Object, Boolean)) As Boolean _
                                    Implements storoomThreadModel.registerCallback
        Return _storoomThreadModel.registerCallback(cbs, d)
    End Function
End Class
